---------------------------------------------------------------------------------
  -- Design Name : Execute and Memory Access Stage
  -- File Name   : ExMemStage.vhd
  -- Function    : Execute and memory access stage
  -- Authors     : Mirko Francuski  2006/0225
  --               Milos Mihajlovic 2006/0039
  -- School      : University of Belgrade
  --               School for Electrical Engineering
  --               Department for Computer Engineering and Information Theory
  -- Subject     : VLSI Computer Systems
---------------------------------------------------------------------------------

library ieee;

use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use work.UserPkg.all;

entity ExMemStage is
  port (
    clk         : in  std_logic;
    wrkIn       : in  std_logic;
    wrkOut      : out std_logic;
    idleIn      : in  std_logic;
    reset       : in  std_logic;
    wr          : in  std_logic;
    newAddr     : in  word32;
    rs1Data     : in  word32;
    rs2Data     : in  word32;
    wbData      : in  word32;
    r1addr      : in  RegAddr;
    r2addr      : in  RegAddr;
    rwr         : in  RegAddr;
    rd          : in  RegAddr;
    op          : in  OpCode;
    adBusReq    : out std_logic;
    ddBusReq    : out std_logic;
    dRd         : out std_logic;
    dWr         : out std_logic;
    opOut       : out OpCode;
    rdOut       : out regAddr := (others => '0');
    aluData     : out word32  := (others => '0');
    adBus       : out word32  := (others => '0');
    ddBus       : out word32  := (others => '0');
    stackData   : out word32  := (others => '0')
  );
end ExMemStage;

architecture behavioral of ExMemStage is
  signal aluAMUXOut     : word32;
  signal aluBMUXOut     : word32;
  signal aluStackMUXOut : word32;
  signal r1In           : regAddr;
  signal r2In           : regAddr;
  signal rdIn           : regAddr;
  signal rwrIn          : regAddr;
  signal aluN           : std_logic;
  signal aluZ           : std_logic;
  signal aluC           : std_logic;
  signal aluV           : std_logic;
  signal stackV         : std_logic;
  signal stackPush      : std_logic;
  signal stackPop       : std_logic;
  signal aluAMUXSel     : std_logic;
  signal aluBMUXSel     : std_logic;
  signal stackMUXSel    : std_logic;
  signal clock          : std_logic;
  signal dRdSignal      : std_logic;
  signal dWrSignal      : std_logic;
  signal dRdOut         : std_logic;
  signal dWrOut         : std_logic;
begin

  aluAMUX: GenMux32_2 port map (
    in1     => rs1Data,
    in2     => wbData,
    sel     => aluAMUXSel,
    muxOut  => aluAMUXOut
  );
  
  aluBMUX: GenMux32_2 port map (
    in1     => rs2Data,
    in2     => wbData,
    sel     => aluBMUXSel,
    muxOut  => aluBMUXOut
  );
  
  alu: ExMemAlu32 port map(
    op      => op,
    in1     => aluAMUXOut,
    in2     => aluBMUXOut,
    alu_out => aluData,
    n       => aluN,
    z       => aluZ,
    c       => aluC,
    v       => aluV
  );
  
  aluStackMUX: GenMux32_2 port map (
    in1     => aluAMUXOut,
    in2     => newAddr,
    sel     => stackMUXSel,
    muxOut  => aluStackMUXOut
  );
  
  stack: ExMemStack32_1024 port map (
    clk     => clock,
    cl      => reset,
    push    => stackPush,
    pop     => stackPop,
    dataIn  => aluStackMUXOut,
    stackV  => stackV,
    dataOut => stackData
  );
  
  ctrl: ExMemCtrl port map (
    stackV        => stackV,
    aluV          => aluV,
    aluN          => aluN,
    aluZ          => aluZ,
    aluC          => aluC,
    wr            => wr,
    op            => op,
    r1addr        => r1addr,
    r2addr        => r2addr,
    rwr           => rwr,
    stackPush     => stackPush,
    stackPop      => stackPop,
    aluAMUXSel    => aluAMUXSel,
    aluBMUXSel    => aluBMUXSel,
    stackMUXSel   => stackMUXSel,
    dRd           => dRdSignal,
    dWr           => dWrSignal,
    workSignal    => wrkIn
  );
  
  dRd      <= dRdOut;
  dWr      <= dWrOut;
  
  adBusReq <= dRdOut or dWrOut;
  ddBusReq <= dWrOut;
  
  adBus <= newAddr;
  ddBus <= aluBMUXOut;
  opOut <= op when idlein = '0' else
           OPC_NOP;
  rdOut <= rd;
  clock <= clk and wrkIn;
  wrkOut <= wrkIn;
  
  dRdOut   <= wrkIn and dRdSignal;
  dWrOut   <= wrkIn and dWrSignal;
  
end architecture behavioral;

